package org.example.spring.ioc;

import org.example.spring.ioc.bean.*;
import org.example.spring.ioc.controller.UserController;
import org.example.spring.ioc.dao.Dao;
import org.example.spring.ioc.dao.DeliveryDao;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ResourceUtils;


import java.io.File;
import java.util.Map;

/**
 * 默认：分层注解能起作用的前提是，这些组件必须再逐层徐所在的包及其子包结构下
 * 这个是主入口类，称为主程序类，启动springboot项目
 */
@SpringBootApplication
public class Spring01IocApplication {

	/*
	* 理解生命周期
	*/
	public static void main(String[] args) {
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
		System.out.println("=================IOC容器创建完成====================");

		User user = ioc.getBean(User.class);
		System.out.println("运行"+user);
	}

	/*
	* 测试@Profile
	*/
	public static void test07(String[] args) {
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
		System.out.println("=================IOC容器创建完成====================");

		DeliveryDao deliveryDao = ioc.getBean(DeliveryDao.class);
		deliveryDao.save();
	}

	/*
	* 测试@Value
	*/
	public static void test06(String[] args) {
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
		System.out.println("=================IOC容器创建完成====================");

		Cat cat = ioc.getBean(Cat.class);
		System.out.println(cat);
	}

	/*
	* 测试自动注入
	*/
	public static void test05(String[] args) {
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
		System.out.println("=================IOC容器创建完成====================");

		Map<String, UserController> userControllerMap = ioc.getBeansOfType(UserController.class);
		//依赖注入在容器启动的时候，容器启动的时候会自动创建对象，并调用对象中的方法，完成注入
		System.out.println("userController="+userControllerMap);
		Map<String, Dao> stringDaoMap = ioc.getBeansOfType(Dao.class);
		System.out.println("stringDaoMap="+stringDaoMap);

		Dao dao = ioc.getBean(Dao.class);
		String environment = dao.getEnvironment();
		System.out.println("osType="+environment);
	}

	/*
	*条件注册
	*/
	public static void test04(String[] args) {
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
		Map<String, person> beansOfType = ioc.getBeansOfType(person.class);
		System.out.println("beansOfType="+beansOfType);
		Map<String, Dog> beansOfType1 = ioc.getBeansOfType(Dog.class);
		System.out.println("beansOfType1="+beansOfType1);
		//拿到环境变量
		ConfigurableEnvironment environment = ioc.getEnvironment();
		String property =environment.getProperty("OS");
		System.out.println("property="+property);
	}

	//FactoryBean在容器中放的组件的类型，是接口中泛型指定的类型，组件的名字是工厂自己的名字
	public static void test03(String[] args) {
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
		System.out.println("=================IOC容器创建完成====================");

		Car car = ioc.getBean(Car.class);
		System.out.println("car="+car);

		Car car1 = ioc.getBean(Car.class);
		System.out.println("car="+car1);

		Map<String, Car> beansOfType = ioc.getBeansOfType(Car.class);
		System.out.println("beansOfType="+beansOfType);

	}


	public static void test02(String[] args) {
		/*
		* 创建时机：容器启动过程中就会创建组件对象
		* 单实例特性：所有组件默认是单实例的，每次获取组件都直接从容器中拿，容器创建完成前创建对象
		*/
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
		System.out.println("=================IOC容器创建完成====================");

		//2.获取容器中的组件
		Dog dog = ioc.getBean(Dog.class);
		System.out.println("dog="+dog);

		Dog dog2 = ioc.getBean(Dog.class);
		System.out.println("dog2="+dog2);
	}

	public static void test01(String[] args) {
		//1.跑起一个spring应用； ApplicationContext: spring容器(IOC容器）
		//spring应用一跑起来返回一个容器
		ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
//		System.out.println("IOC="+ioc);
//
//		//2.查看容器里面的组件 ; spring启动会有很多默认组件
//		System.out.println("================================");
//		String[] names = ioc.getBeanDefinitionNames();
//		for(String name:names){
//			System.out.println("names="+name);
//		}

		//4、获取容器中的组件对象
		//组件的四大特性：名字、类型、作用域、对象
		//组件名字全局唯一；组件名重复了，一定只会给容器中放一个最先声明的一个

		//小结：
		//从容器中获取组件：
		//  1）组件不存在，抛异常：NoSuchBeanDefinitionException
		//  2）组件不唯一，
		//     按照类型只要一个：抛异常：NoUniqueBeanDefinitionException
		//     按照类型多个：返回所有组件的List集合
		//  3）组件不唯一，按照名字获取
		//  4）组件唯一存在，正确返回


		//4.1按照组件名字获取对象
		Object ob1=ioc.getBean("haha");
		System.out.println("haha="+ob1);

		//4.2按照组件类型获取对象
//		person ob2 = ioc.getBean(person.class);
//		System.out.println("person="+ob2);
		Map<String,person>type=ioc.getBeansOfType(person.class);
		System.out.println("type="+type);

		//4.4按照类型+名字获取对象
		person ob3 = ioc.getBean("haha", person.class);
		System.out.println("haha="+ob3);
	}





}
